package com.jyniubi.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jyniubi.base.exception.Assert;
import com.jyniubi.base.exception.BussinessException;
import com.jyniubi.base.result.ResponseEnum;
import com.jyniubi.base.utils.IpUtils;
import com.jyniubi.base.utils.JwtUtils;
import com.jyniubi.common.utils.MD5;
import com.jyniubi.core.pojo.entity.UserAccount;
import com.jyniubi.core.pojo.entity.UserInfo;
import com.jyniubi.core.mapper.UserInfoMapper;
import com.jyniubi.core.pojo.entity.UserLoginRecord;
import com.jyniubi.core.pojo.vo.UserInfoSearchVO;
import com.jyniubi.core.pojo.vo.UserInfoVo;
import com.jyniubi.core.pojo.vo.UserResponseVO;
import com.jyniubi.core.service.UserAccountService;
import com.jyniubi.core.service.UserInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jyniubi.core.service.UserLoginRecordService;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.UUID;

/**
 * <p>
 * 用户基本信息 服务实现类
 * </p>
 *
 * @author jyzhang
 * @since 2024-04-27
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Resource
    UserAccountService userAccountService;
    @Resource
    UserLoginRecordService userLoginRecordService;
    @Override
    public void register(UserInfoVo userInfoVo) {
        String code = userInfoVo.getCode();
        String phone = userInfoVo.getMobile();
        String password = userInfoVo.getPassword();
        Integer userType = userInfoVo.getUserType();
        // 判断此手机号是否已经注册
        // todo : 个人感觉这边手机号判断是否注册没有必要写，在发送验证码的时候已经验证手机号是否重复了
        //  手机号没有重复才会收到验证码，才能执行下面的代码，接口顺序的问题，所以判断了两回
        int count = this.count(Wrappers.lambdaQuery(UserInfo.class).eq(UserInfo::getMobile, phone));
        Assert.assertTrue(count>0,ResponseEnum.MOBILE_EXIST_ERROR);
        // 获取code ，然后和redis存储的code作比较
        String redisCode = stringRedisTemplate.opsForValue().get("sms:code:" + phone);
        Assert.assertTrue(redisCode==null || !StringUtils.equals(code,redisCode), ResponseEnum.CODE_ERROR);
        // 密码加密
        String salt = UUID.randomUUID().toString().substring(0,6);
        String encryptPsd = MD5.encrypt(MD5.encrypt(password) + salt);
        //将数据存到数据库表中
        UserInfo userInfo = new UserInfo();
        userInfo.setMobile(phone);
        userInfo.setUserType(userType);
        userInfo.setPassword(encryptPsd);
        userInfo.setNickName("菜鸟_" + UUID.randomUUID().toString().substring(0,6));
        userInfo.setHeadImg("https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        userInfo.setIntegral(0);
        userInfo.setStatus(1);
        userInfo.setSalt(salt);
        this.save(userInfo);
        stringRedisTemplate.delete("sms:code:" + phone);
        UserAccount userAccount = new UserAccount();
        userAccount.setUserId(userInfo.getId());
        userAccount.setAmount(BigDecimal.ZERO);
        userAccount.setFreezeAmount(BigDecimal.ZERO);
        userAccountService.save(userAccount);
    }

    @Override
    public UserResponseVO login(UserInfoVo userInfoVo, HttpServletRequest request) {
        //1.校验参数 controller层
        String phone = userInfoVo.getMobile();
        String password = userInfoVo.getPassword();
        Integer userType = userInfoVo.getUserType();
        //2.根据手机号查询数据库密码和盐 然后加密之后和数据库中的密码比较
        UserInfo userInfo = this.getOne(Wrappers.lambdaQuery(UserInfo.class)
                .eq(UserInfo::getUserType, userType)
                .eq(UserInfo::getMobile, phone));
        Assert.assertTrue(userInfo == null,ResponseEnum.LOGIN_MOBILE_ERROR);
        String encryptPsd = MD5.encrypt(MD5.encrypt(password) + userInfo.getSalt());
        Assert.assertTrue(!encryptPsd.equals(userInfo.getPassword()),ResponseEnum.LOGIN_PASSWORD_ERROR);
        //3.封装数据
        UserResponseVO userResponseVO = new UserResponseVO();
        userResponseVO.setUserType(userType);
        userResponseVO.setHeadImg(userInfo.getHeadImg());
        userResponseVO.setNickName(userInfo.getNickName());
        String token = JwtUtils.createToken(userInfo.getId(), userInfo.getNickName());
        userResponseVO.setToken(token);
        // 保存用户登录日志
        UserLoginRecord userLoginRecord = new UserLoginRecord();
        userLoginRecord.setIp(IpUtils.getIpAddressAtService(request));
        userLoginRecord.setUserId(userInfo.getId());
        userLoginRecord.setCreateTime(new Date());
        userLoginRecord.setUpdateTime(new Date());
        userLoginRecordService.save(userLoginRecord);

        return userResponseVO;
    }

    @Override
    public Page<UserInfo> listPage(UserInfoSearchVO userInfoSearchVO, Integer pageNum, Integer pageSize) {
        Page<UserInfo> page = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<UserInfo> queryWrapper = Wrappers.lambdaQuery(UserInfo.class);
        String mobile = userInfoSearchVO.getMobile();
        Integer status = userInfoSearchVO.getStatus();
        Integer userType = userInfoSearchVO.getUserType();
        if (!StringUtils.isBlank(mobile)){
            queryWrapper.like(UserInfo::getMobile,mobile);
        }
        if (status != null){
            queryWrapper.eq(UserInfo::getStatus,status);
        }
        if (userType != null){
            queryWrapper.eq(UserInfo::getUserType,userType);
        }
        this.page(page,queryWrapper);

        return page;
    }
}
